﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.IO;

namespace Articles.LinqDynamicWhere
{
    public static class FileSearch
    {
        /// <summary>
        /// Return a DirectoryInfo object based on the string path provided
        /// </summary>
        /// <param name="path">the folder path</param>
        /// <returns>DirectoryInfo object</returns>
        public static DirectoryInfo Folder(string path)
        {
            return new DirectoryInfo(path);
        }
        /// <summary>
        /// Predicate function to match keyword in Name of files
        /// </summary>
        /// <param name="keywords">string list of keywords to search</param>
        /// <returns>boolean(predicate)</returns>
        public static Expression<Func<FileInfo, bool>> ContainsInName(
                                                    params string[] keywords)
        {
            var predicate = PredicateBuilder.False<FileInfo>();
            foreach (string keyword in keywords)
            {
                string temp = keyword;
                predicate = predicate.Or(p => p.Name.Contains(temp));
            }
            return predicate;
        }

        /// <summary>
        /// Predicate function 
        /// </summary>to match a list of files extensions
        /// <param name="keywords">string list of extensions to find</param>
        /// <returns>boolean(predicate)</returns>
        public static Expression<Func<FileInfo, bool>> ExtensionLike(
                                                    params string[] keywords)
        {
            var predicate = PredicateBuilder.False<FileInfo>();
            foreach (string keyword in keywords)
            {
                string temp = keyword;
                predicate = predicate.Or(p => p.Extension == temp);
            }
            return predicate;
        }

        /// <summary>
        /// Extension method to search in File List
        /// </summary>
        /// <param name="dir">DirectoryInfo object</param>
        /// <param name="exts">the list of file extensions to search for</param>
        /// <param name="names">the list of keywords to search for in file names</param>
        /// <param name="recursivity">SearchOption enum</param>
        /// <returns></returns>
        public static List<FileInfo> SearchInFiles(
            this DirectoryInfo dir, string[] exts, string[] names, SearchOption recursivity)
        {
            var predicate = PredicateBuilder.True<FileInfo>();

            if (exts.Length > 0)
                predicate = predicate.And(ExtensionLike(exts));
            if (names.Length > 0)
                predicate = predicate.And(ContainsInName(names));

            List<FileInfo> files = (
                    from f in dir.GetFiles("*.*", recursivity)
                    select f
                    ).AsQueryable<FileInfo>()
                    .Where<FileInfo>(predicate)
                    .ToList<FileInfo>();

            return files;
        }
    }
}
